package org.swift.mashup.wsdl;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.xml.stream.XMLStreamException;

import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.xpath.AXIOMXPath;
import org.apache.log4j.Logger;
import org.jaxen.JaxenException;
import org.swift.commons.xml.OMUtils;

public class SOAPUtil {
	private static final Logger logger = Logger.getLogger(SOAPUtil.class);
	
	@SuppressWarnings("unchecked")
	public static Map<String, OMNamespace> getInputParamsNamespaces (String message) throws JaxenException, XMLStreamException{
		Map<String,OMNamespace> paramNamespaces = new HashMap<String,OMNamespace>();
		Iterator<OMElement> children = selectBodyElement(message).getChildElements();
		while (children.hasNext()){
			OMElement child = children.next();
			if (child.getNamespace() != null){
				paramNamespaces.put(child.getLocalName(), child.getNamespace());
			} else if (child.getDefaultNamespace() != null){
				paramNamespaces.put(child.getLocalName(), child.getDefaultNamespace());
			}
		}
		return paramNamespaces;
	}
	
	public static OMElement selectBodyElement (String message) throws JaxenException, XMLStreamException{
		return selectBodyElement(OMUtils.stringToOMElement(message));
	}
	
	public static OMElement selectBodyElement (OMElement message) throws JaxenException {
		String prefix = getNamespacePrefix(message);
		String xpath = "/" + prefix + "Envelope/" + prefix + "Body";
		if (logger.isDebugEnabled()){
			logger.debug("Looking for the soap body.  Trying xpath: " + xpath
				+ " on\n" + message.toString());
		}
		OMElement el = (OMElement) createXPath(message,xpath).selectSingleNode(
				message);
		if (el != null && el.getFirstElement() != null)
			return el.getFirstElement();
		logger.debug("Soap body not found.");
		return message;
	}
	
	private static String getNamespacePrefix(OMElement message) {
		try {
			String nsPrefix = message.getNamespace().getPrefix().trim();
			if (nsPrefix.length() > 0)
				return nsPrefix + ":";
			else
				return nsPrefix;
		} catch (NullPointerException npe){
			return "";
		}
	}
	
	@SuppressWarnings("unchecked")
	private static AXIOMXPath createXPath(OMElement message, String path) throws JaxenException {
		AXIOMXPath xpath = new AXIOMXPath(path);
		Iterator<OMNamespace> nsIter = message.getAllDeclaredNamespaces();
		while (nsIter.hasNext()) {
			OMNamespace currentNs = nsIter.next();
			xpath.addNamespace(currentNs.getPrefix(), currentNs
					.getNamespaceURI());
		}
		return xpath;
	}
}
